package com.university.evaluation.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.university.evaluation.common.ResponseResult;
import com.university.evaluation.domain.dto.UpdateUserDTO;
import com.university.evaluation.domain.dto.UserRegisterDTO;
import com.university.evaluation.entity.User;
import com.university.evaluation.enums.RespEnum;
import com.university.evaluation.mapper.UserMapper;
import com.university.evaluation.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;

@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private PasswordEncoder passwordEncoder;

    /**
     * 注意：此 login 方法在当前的 Spring Security 认证流程中已不被直接调用。
     * 认证的核心逻辑在 UserDetailsServiceImpl 和 AuthenticationProvider 中。
     * 此方法可保留用于未来可能的、非Security流程的登录场景。
     */
    @Override
    public User login(String username, String password) {
        User user = this.findByStudentId(username);
        if (user == null) throw new BadCredentialsException("学号或密码错误");
        if (user.getStatus() != 1) throw new BadCredentialsException("账号已被禁用");
        if (!passwordEncoder.matches(password, user.getPassword())) throw new BadCredentialsException("学号或密码错误");
        return user;
    }

    /**
     * 根据学号/工号查询用户 (用于认证)
     */
    @Override
    public User findByStudentId(String studentId) {
        if (!StringUtils.hasText(studentId)) return null;
        return baseMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getStudentId, studentId.trim()));
    }

    /**
     * 根据用户名/昵称查询用户
     */
    @Override
    public User findByUsername(String username) {
        if (!StringUtils.hasText(username)) return null;
        return baseMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getUsername, username.trim()));
    }

    /**
     * 修改密码
     */
    @Override
    public ResponseResult<Void> updatePassword(Long userId, String oldPassword, String newPassword) {
        User user = getById(userId);
        if (user == null) {
            return ResponseResult.failure(RespEnum.NOT_FOUND.getCode(), "用户不存在");
        }
        if (!passwordEncoder.matches(oldPassword, user.getPassword())) {
            return ResponseResult.failure(RespEnum.OLD_PASSWORD_ERROR);
        }
        user.setPassword(passwordEncoder.encode(newPassword));
        boolean success = updateById(user);
        return success ? ResponseResult.success("密码修改成功") : ResponseResult.failure("密码修改失败，请稍后再试");
    }

    @Override
    public ResponseResult<Void> updateUserAvatar(Long userId, String avatarUrl) {
        try {
            User user = getById(userId);
            if (user == null) {
                return ResponseResult.failure(404, "用户不存在");
            }
            
            // 使用UpdateWrapper精确更新avatar字段
            UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("id", userId);
            updateWrapper.set("avatar", avatarUrl);
            
            boolean success = update(updateWrapper);
            if (success) {
                log.info("用户 {} 头像更新成功: {}", userId, avatarUrl);
                return ResponseResult.success("头像更新成功");
            } else {
                log.error("用户 {} 头像更新失败", userId);
                return ResponseResult.failure("头像更新失败");
            }
        } catch (Exception e) {
            log.error("更新用户头像异常: {}", e.getMessage(), e);
            return ResponseResult.failure("系统异常，请稍后再试");
        }
    }

    /**
     * 重置密码 (管理员操作)
     */
    @Override
    public ResponseResult<Void> resetPassword(Long userId, String newPassword) {
        User user = getById(userId);
        if (user == null) {
            return ResponseResult.failure(RespEnum.NOT_FOUND.getCode(), "用户不存在");
        }
        user.setPassword(passwordEncoder.encode(newPassword));
        boolean success = updateById(user);
        return success ? ResponseResult.success("密码重置成功") : ResponseResult.failure("密码重置失败，请稍后再试");
    }

    /**
     * [MODIFIED] 注册用户 (适配学号+用户名模式，并处理真实姓名)
     */
    @Override
    @Transactional
    public ResponseResult<User> register(UserRegisterDTO userRegisterDTO) {
        // 检查学号/工号是否已存在
        if (studentIdIsExist(userRegisterDTO.getStudentId())) {
            return ResponseResult.failure(RespEnum.STUDENT_ID_EXIST);
        }

        User user = new User();
        user.setStudentId(userRegisterDTO.getStudentId());

        // 默认将学号作为初始用户名/昵称，用户后续可以修改
        user.setUsername(userRegisterDTO.getStudentId());
        user.setPassword(passwordEncoder.encode(userRegisterDTO.getPassword()));

        user.setCreateTime(LocalDateTime.now());
        user.setStatus(1); // 默认启用

        boolean success = save(user);
        if (success) {
            log.info("新用户注册成功，学号: {}", user.getStudentId());
            user.setPassword(null); // 返回前清除密码
            return ResponseResult.success("注册成功", user);
        } else {
            log.error("用户注册失败，数据库操作异常，学号: {}", userRegisterDTO.getStudentId());
            return ResponseResult.failure(RespEnum.FAILURE.getCode(), "注册失败，请联系管理员");
        }
    }

    /**
     * [MODIFIED] 更新用户信息 (使用UpdateWrapper精确控制更新字段)
     */
    @Override
    @Transactional
    public ResponseResult<Void> updateUserInfo(Long userId, UpdateUserDTO updateUserDTO) {
        if (userId == null) {
            return ResponseResult.failure(RespEnum.NOT_FOUND.getCode(), "用户ID不能为空");
        }

        try {
            // 使用 UpdateWrapper 来精确控制哪些字段需要更新
            UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("id", userId);
            
            boolean hasUpdate = false; // 标记是否有更新操作

            // 从 DTO 中有选择地设置更新字段（只设置非空值）
            if (StringUtils.hasText(updateUserDTO.getName())) {
                updateWrapper.set("real_name", updateUserDTO.getName());
                hasUpdate = true;
            }
            if (StringUtils.hasText(updateUserDTO.getRealName())) {
                updateWrapper.set("real_name", updateUserDTO.getRealName());
                hasUpdate = true;
            }
            if (StringUtils.hasText(updateUserDTO.getStudentId())) {
                updateWrapper.set("student_id", updateUserDTO.getStudentId());
                hasUpdate = true;
            }
            if (StringUtils.hasText(updateUserDTO.getUsername())) {
                // 检查新昵称是否已被其他用户占用
                if (usernameIsExist(updateUserDTO.getUsername())) {
                    return ResponseResult.failure(RespEnum.USERNAME_EXIST);
                }
                updateWrapper.set("username", updateUserDTO.getUsername());
                hasUpdate = true;
            }
            if (StringUtils.hasText(updateUserDTO.getEmail())) {
                updateWrapper.set("email", updateUserDTO.getEmail());
                hasUpdate = true;
            }
            if (StringUtils.hasText(updateUserDTO.getPhone())) {
                updateWrapper.set("phone", updateUserDTO.getPhone());
                hasUpdate = true;
            }
            if (StringUtils.hasText(updateUserDTO.getGender())) {
                updateWrapper.set("gender", updateUserDTO.getGender());
                hasUpdate = true;
            }
            if (updateUserDTO.getBirthDate() != null) {
                updateWrapper.set("birth_date", updateUserDTO.getBirthDate());
                hasUpdate = true;
            }
            if (StringUtils.hasText(updateUserDTO.getAddress())) {
                updateWrapper.set("address", updateUserDTO.getAddress());
                hasUpdate = true;
            }
            // 注意：移除avatar字段的更新逻辑，头像现在通过专门的文件上传接口处理
            if (StringUtils.hasText(updateUserDTO.getClassName())) {
                updateWrapper.set("class_name", updateUserDTO.getClassName());
                hasUpdate = true;
            }
            if (StringUtils.hasText(updateUserDTO.getCollege())) {
                updateWrapper.set("college", updateUserDTO.getCollege());
                hasUpdate = true;
            }
            if (updateUserDTO.getCollegeId() != null) {
                updateWrapper.set("college_id", updateUserDTO.getCollegeId());
                hasUpdate = true;
            }
            if (StringUtils.hasText(updateUserDTO.getGrade())) {
                updateWrapper.set("grade", updateUserDTO.getGrade());
                hasUpdate = true;
            }
            if (StringUtils.hasText(updateUserDTO.getMajor())) {
                updateWrapper.set("major", updateUserDTO.getMajor());
                hasUpdate = true;
            }
            if (updateUserDTO.getEmailVerified() != null) {
                updateWrapper.set("email_verified", updateUserDTO.getEmailVerified());
                hasUpdate = true;
            }
            if (updateUserDTO.getPhoneVerified() != null) {
                updateWrapper.set("phone_verified", updateUserDTO.getPhoneVerified());
                hasUpdate = true;
            }
            if (updateUserDTO.getRoleId() != null) {
                updateWrapper.set("role_id", updateUserDTO.getRoleId());
                hasUpdate = true;
            }
            if (updateUserDTO.getStatus() != null) {
                updateWrapper.set("status", updateUserDTO.getStatus());
                hasUpdate = true;
            }

            // 兼容旧字段
            if (StringUtils.hasText(updateUserDTO.getDepartment())) {
                updateWrapper.set("college", updateUserDTO.getDepartment());
                hasUpdate = true;
            }
            if (updateUserDTO.getYear() > 0) {
                updateWrapper.set("grade", String.valueOf(updateUserDTO.getYear()));
                hasUpdate = true;
            }

            // 始终更新时间
            updateWrapper.set("update_time", LocalDateTime.now());
            hasUpdate = true;

            if (!hasUpdate) {
                return ResponseResult.success("没有需要更新的字段");
            }

            // 执行更新（只更新指定的字段）
            boolean success = this.update(updateWrapper);

            if (success) {
                log.info("用户ID {} 的信息已成功更新", userId);
                return ResponseResult.success("用户信息更新成功");
            } else {
                log.warn("更新用户ID {} 的信息失败，可能用户不存在", userId);
                return ResponseResult.failure(404, "更新失败，找不到该用户");
            }
        } catch (Exception e) {
            log.error("更新用户信息时发生数据库异常", e);
            return ResponseResult.failure("更新失败，服务器内部错误: " + e.getMessage());
        }
    }

    /**
     * 检查学号/工号是否存在
     */
    private boolean studentIdIsExist(String studentId) {
        if (!StringUtils.hasText(studentId)) return false;
        return baseMapper.exists(new LambdaQueryWrapper<User>().eq(User::getStudentId, studentId.trim()));
    }

    /**
     * 检查用户名/昵称是否存在
     */
    private boolean usernameIsExist(String username) {
        if (!StringUtils.hasText(username)) return false;
        return baseMapper.exists(new LambdaQueryWrapper<User>().eq(User::getUsername, username.trim()));
    }

    /**
     * 获取用户详细信息
     */
    @Override
    public ResponseResult<User> getUserInfo(Long userId) {
        try {
            User user = getById(userId);
            if (user != null) {
                // 清除密码信息
                user.setPassword(null);
                return ResponseResult.success("获取成功", user);
            } else {
                return ResponseResult.failure(RespEnum.NOT_FOUND.getCode(), "用户不存在");
            }
        } catch (Exception e) {
            log.error("获取用户信息时发生异常, userId: {}", userId, e);
            return ResponseResult.failure("获取用户信息失败");
        }
    }

    /**
     * 根据学号获取用户详细信息
     */
    @Override
    public ResponseResult<User> getUserInfoByStudentId(String studentId) {
        try {
            User user = findByStudentId(studentId);
            if (user != null) {
                // 清除密码信息
                user.setPassword(null);
                return ResponseResult.success("获取成功", user);
            } else {
                return ResponseResult.failure(RespEnum.NOT_FOUND.getCode(), "用户不存在");
            }
        } catch (Exception e) {
            log.error("根据学号获取用户信息时发生异常, studentId: {}", studentId, e);
            return ResponseResult.failure("获取用户信息失败");
        }
    }
}